package utils;

import java.util.ArrayList;
import java.util.HashSet;

import models.cards.EpidemicCard;
import models.cards.IInfectionCard;
import models.cards.IPlayerCard;
import models.cards.InfectionCityCard;
import models.city.City;
import models.game.Game;
import models.players.Player;

public class GameUtils {

	private final static String initialLocation = "Atlanta";

	public synchronized static void initGame(Game game) {

		game.getPlayerDeck().shuffleDeck();
		game.getInfectionDeck().shuffleDeck();

		City startCity = game.getCities().get(initialLocation);

		// draw initial player cards
		for (Player player : game.getPlayers().values()) {
			for (int i = 0; i < 2; i++) {
				player.putCardInHand((IPlayerCard) game.getPlayerDeck()
						.drawCard());
			}
			player.setLocation(startCity); // set player's initial location
		}
		startCity.setHasResearchCentre(true); // set a research station in the
												// start city
		// draw initial infection cards
		for (int k = 0; k < 3; k++) {
			for (int i = 3; i > 0; i--) {
				IInfectionCard card = (IInfectionCard) game.getInfectionDeck()
						.drawCard();
				if (card instanceof InfectionCityCard) {
					for (int j = 0; j < i; j++) {
						simpleInfect(((InfectionCityCard) card).getCity(), game);
					}
				}
			}
		}
		// add epidemic cards to player deck
		for (int i = 0; i < 4; i++) {
			game.getPlayerDeck().addToDeck(new EpidemicCard());
		}
		game.getPlayerDeck().shuffleDeck();

	}

	private synchronized static void simpleInfect(City city, Game game) {
		if (city.getHasOutbreaked() == false) {
			if (city.getDisease().getIsEradicated() == false) {
				if (city.getInfectionLevel() < 3) {
					city.increaseInfectionLevel();
					city.getDisease().decreaseInfectionsLeft();
					addToLog(game, (city.getName() + " got infected"));
				} else {
					city.setHasOutbreaked(true);
					outbreak(city, game);
				}
			}
		}
	}

	private synchronized static void increaseOutbreaks(Game game) {
		game.setOutbreaks(game.getOutbreaks() + 1);
	}

	private synchronized static void outbreak(City city, Game game) {
		addToLog(game, (city.getName() + " outbreaked"));
		increaseOutbreaks(game);
		for (City otherCity : getNeighbours(city, game)) {
			simpleInfect(otherCity, game);
		}

	}

	public synchronized static void infect(Game game) {
		IInfectionCard card = (IInfectionCard) game.getInfectionDeck()
				.drawCard();
		if (card instanceof InfectionCityCard) {
			simpleInfect(((InfectionCityCard) card).getCity(), game);
		}
	}

	private synchronized static HashSet<City> getNeighbours(City city, Game game) {
		HashSet<City> neighbours = new HashSet<City>();
		for (String name : city.getNeighbourNames()) {
			neighbours.add(game.getCities().get(name));
		}
		return neighbours;
	}

	public synchronized static void drawPlayerCards(Player player, Game game) {
		IPlayerCard card = (IPlayerCard) game.getPlayerDeck().drawCard();
		if (card instanceof EpidemicCard) {
			addToLog(game, "Epidemic card was drawn");
			IInfectionCard bottomCard = game.getInfectionDeck()
					.drawCardFromBottom();
			for (int i = 0; i < 3; i++) {
				if (bottomCard instanceof InfectionCityCard) {
					simpleInfect(((InfectionCityCard) bottomCard).getCity(),
							game);
				}
			}

			game.getPlayerDeck().addToDiscardPile(card);

			game.getInfectionDeck().addDiscardPileToDeck();
		} else {
			player.putCardInHand(card);
		}
	}

	private synchronized static void addToLog(Game game, String log) {
		ArrayList<String> loglist = game.getLog();
		loglist.add(log);
		game.setLog(loglist);
	}

}
